/*
 * File:       eg_geom.h
 * Created on: Aug 26, 2009
 * Purpose:    Contains functions dealing with geometry
 */

/*
 Copyright 2009 James Youngquist, Colin Scott.

 This file is part of ElectroGladiator.  ElectroGladiator is free
 software: you can redistribute it and/or modify it under the terms
 of the GNU General Public License as published by  the Free
 Software Foundation, either version 3 of the License, or (at your
 option) any later version.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef EG_GEOM_H_
#define EG_GEOM_H_ 1

#include "eg_data.h"

/* looks for intersection */
int intersection(const Line *l1, const Line *l2, Point *p);

/**
 * Finds all intersections along line l and adds them to inters as new points
 * allocated in memory.
 * Returns Point closest to a player from a list of Points.  This clears the
 * list.
 */
void find_intersections(Map *map, Line *l, LL *inters);

Point* closest_point(Player *p, LL *inters);

// Returns the Line in a Map that contains the given Point. Ugly hax right
// now; need a more elegant way than checking intersections with a line all
// over again to make this function more generic.  Good thing to check
// mathematically, but I don't know accuracy of floating point numbers like
// that. Another problem is to return the correct line when 2+ lines all
// satisfy the intersection test, e.g. where several lines share the same
// end point, but not all of them may be in the FOV.
Line* line_with_point(Map *map, Point *p, Line *FR_l, Line *FL_l, Player *pl);

// True if this point is an endpoint of the line
int is_endpoint(Point *p, Line *l);

// Returns opposite end point.  Pre: p is an end point
Point* other_endpoint(Point *p, Line *l);

/* Returns which of 1 or 2 in p1 and p2 is the left end point of a line from
 the player's perspective. Careful not to mung the point's values...
 This functions acts as though the player's bearing is towards the closest
 point on the line to the player.
 */
Point* left_point(const Player *p, Line *l);

/* Returns which of 1 or 2 in p1 and p2 is the right end point of a line from
 the player's perspective. Careful not to mung the point's values...
 */
Point* right_point(const Player *p, Line *l);

// Returns if two points are roughly the same
int same_point(Point *p1, Point *p2);

// Returns if two angles are roughly the same
int same_angle(double a, double b);

// returns 0 <= a < 2*PI
double normalize_angle(double a);

// returns angle from origin to point, 0 <= angle < 2*PI
double angle_to_point(Point origin, Point p);

// returns distance from origin of a point
double distance(const Point *p);

/**
 * @param l Line to measure length
 * @return Length of l
 */
double line_length(const Line *l);

// changes a point to polar coords. The distance is stored in x and angle in y.
// The angle is between 0 and 2*PI.
Point* r2p(Point *p);

// changes a point to rectangular coords
Point* p2r(Point *p);

// returns quadrant point is in
int quadrant(const Point *p);

// returns slope of the line, no vertical line test
double slope(const Line *l);

// returns 1 if line is vertical, else 0.
int is_vertical(const Line *l);

// interior angle of <BAC in radians
double interior_angle(Point b, Point a, Point c);

// Returns 1 if a point is within the bounding box defined by the end points of
// a Line, 0 otherwise.
int inside_bb(const Line *l, const Point *p);

// Returns 1 if a point is inside the triangle, 0 otherwise
int inside_tri(const Trigon *t, const Point *p);

// Returns 1 if a point is inside the quadrilateral defined by the end points of
// 2 Lines, 0 otherwise
int inside_quad(const Line *l_1, const Line *l_2, Point *p);

#endif /* EG_GEOM_H_ */
